home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Power 1997 December
/
MACPOWER-1997-12.ISO.7z
/
MACPOWER-1997-12.ISO
/
AMUG
/
PROGRAMMING
/
Raven 1.2 Examples.sit
/
Raven 1.2 Examples
/
Quill
/
Source
/
PenDialog.cpp
< prev
next >
Wrap
Text File
|
1997-08-26
|
13KB
|
535 lines
/*
* File: PenDialog.cpp
* Function: A dialog that allows the user to edit an SPen.
* Written by: Jesse Jones
*
* Copyright ゥ 1997 Jesse Jones.
* For conditions of distribution and use, see copyright notice in ZTypes.h
*
* Change History (most recent first):
*
* <1> 5/04/97 JDJ Created
*/
#include "PenDialog.h"
#include <Fp.h>
#include <List.h>
#include <Resources.h>
#include <ZApplication.h>
#include <ZColorSwatch.h>
#include <ZDialogHandler.h>
#include <ZMenuBar.h>
#include <ZNumbers.h>
#include <ZPatternSwatch.h>
#include <ZQDShapes.h>
#include <ZStringUtils.h>
#include "ClickNotifier.h"
#include "DialogBoxProxy.h"
#include "WindowProxy.h"
// ===================================================================================
// class CRandomWalk
// ===================================================================================
class CRandomWalk : public TPane {
typedef TPane Inherited;
//-----------------------------------
// Initialization/Destruction
//
public:
virtual ~CRandomWalk();
CRandomWalk(TView* superView);
static MReanimatable* Create(MReanimatable* parent);
//-----------------------------------
// New API
//
public:
void Restart();
// Start walking all over again.
void SetPen(const SPen& pen);
//-----------------------------------
// Inherited API
//
protected:
virtual void OnReanimated();
virtual bool OnMouseDown(const TMouseEvent& event);
virtual void OnDraw(TCanvas& canvas, const TRegion& dirtyRgn);
//-----------------------------------
// Member data
//
protected:
SPen mPen;
list<TPoint, allocator<TPoint> > mPath;
};
static TReanimatorRegister<CRandomWalk> sRandomWalkRegistrar;
//---------------------------------------------------------------
//
// CRandomWalk::~CRandomWalk
//
//---------------------------------------------------------------
CRandomWalk::~CRandomWalk()
{
}
//---------------------------------------------------------------
//
// CRandomWalk::CRandomWalk
//
//---------------------------------------------------------------
CRandomWalk::CRandomWalk(TView* superView) : TPane(superView)
{
}
//---------------------------------------------------------------
//
// CRandomWalk::Create [static]
//
//---------------------------------------------------------------
MReanimatable* CRandomWalk::Create(MReanimatable* parent)
{
return new CRandomWalk(dynamic_cast<TView*>(parent));
}
//---------------------------------------------------------------
//
// CRandomWalk::SetPen
//
//---------------------------------------------------------------
void CRandomWalk::SetPen(const SPen& pen)
{
mPen = pen;
this->Invalidate();
}
//---------------------------------------------------------------
//
// CRandomWalk::Restart
//
//---------------------------------------------------------------
void CRandomWalk::Restart()
{
mPath.resize(0);
TRect extent = this->GetExtent();
short max = Max(extent.GetWidth()/10, extent.GetHeight()/10, 1);
TPoint prevPt;
prevPt.h = extent.left + extent.GetWidth()/2; // start in the center
prevPt.v = extent.top + extent.GetHeight()/2;
mPath.push_back(prevPt);
// Do a random walk until we exit the pane or we bounce around
// a hundred times.
bool hitEdge = false;
for (long index = 1; index <= 100 && !hitEdge; index++) {
short length = Random(max);
double angle = Random(2*pi);
TPoint nextPt;
nextPt.h = prevPt.h + length*cos(angle);
nextPt.v = prevPt.v + length*sin(angle);
hitEdge = !extent.Contains(nextPt);
mPath.push_back(nextPt);
prevPt = nextPt;
}
this->Invalidate();
}
//---------------------------------------------------------------
//
// CRandomWalk::OnReanimated
//
//---------------------------------------------------------------
void CRandomWalk::OnReanimated()
{
Inherited::OnReanimated();
this->Restart();
}
//---------------------------------------------------------------
//
// CRandomWalk::OnMouseDown
//
//---------------------------------------------------------------
bool CRandomWalk::OnMouseDown(const TMouseEvent& event)
{
#pragma unused(event)
this->Restart();
return kHandled;
}
//---------------------------------------------------------------
//
// CRandomWalk::OnDraw
//
//---------------------------------------------------------------
void CRandomWalk::OnDraw(TCanvas& canvas, const TRegion& dirtyRgn)
{
#pragma unused(dirtyRgn)
if (mPath.size() > 1) {
list<TPoint, allocator<TPoint> >::iterator iter = mPath.begin();
TPoint prev = *iter++;
while (iter != mPath.end()) {
TPoint next = *iter++;
TLineShape::Draw(canvas, prev, next, mPen);
prev = next;
}
}
}
#pragma mark -
// ===================================================================================
// class CPenDialog
// ===================================================================================
static TReanimatorRegister<CPenDialog> sPenEditorRegistrar;
//---------------------------------------------------------------
//
// CPenDialog::~CPenDialog
//
//---------------------------------------------------------------
CPenDialog::~CPenDialog()
{
}
//---------------------------------------------------------------
//
// CPenDialog::CPenDialog
//
//---------------------------------------------------------------
CPenDialog::CPenDialog()
{
}
//---------------------------------------------------------------
//
// CPenDialog::Create [static]
//
//---------------------------------------------------------------
MReanimatable* CPenDialog::Create(MReanimatable* parent)
{
ASSERT(parent == nil);
if (CWindowProxy::msUseProxy)
return CDialogBoxProxy::Create(parent);
else
return new CPenDialog;
}
//---------------------------------------------------------------
//
// CPenDialog::Pose [static]
//
//---------------------------------------------------------------
bool CPenDialog::Pose(const string& penName, const SPen& oldPen, SPen* newPen)
{
ASSERT(newPen != nil);
CPenDialog* dialog = dynamic_cast<CPenDialog*>(TDialogBox::Create(242, TApplication::Instance()));
dialog->SetData(oldPen);
dialog->SetName(penName);
string message = kNothingMessage;
{
TDialogHandler handler(dialog);
dialog->Show();
while (message != kCancelMessage && message != kOKMessage) {
message = handler.ProcessNextEvent();
if (message == kOKMessage && !dialog->Validate())
message = kNothingMessage;
}
}
if (message == kOKMessage)
*newPen = dialog->GetData();
return message == kOKMessage;
}
//---------------------------------------------------------------
//
// CPenDialog::HandleMouseDown
//
//---------------------------------------------------------------
bool CPenDialog::HandleMouseDown(const TMouseEvent& event)
{
PRECONDITION(true);
TColorSwatch* swatch1 = dynamic_cast<TColorSwatch*>(this->FindSubPane("Color"));
ASSERT(swatch1 != nil);
TPatternSwatch* swatch2 = dynamic_cast<TPatternSwatch*>(this->FindSubPane("Pattern"));
ASSERT(swatch2 != nil);
TRGBColor color = swatch1->GetColor();
Pattern pattern = swatch2->GetPattern();
bool handled = Inherited::HandleMouseDown(event);
// We can't use CClickNotifier because we need to call SetData
// after the swatch handles the click.
if (handled && (swatch1->GetColor() != color) || (swatch2->GetPattern() != pattern)) {
SPen traits = this->GetData();
this->SetData(traits);
}
POSTCONDITION(true);
return handled;
}
//---------------------------------------------------------------
//
// CPenDialog::HandleContextMenu
//
//---------------------------------------------------------------
bool CPenDialog::HandleContextMenu(const TMouseEvent& event)
{
PRECONDITION(true);
TColorSwatch* swatch1 = dynamic_cast<TColorSwatch*>(this->FindSubPane("Color"));
ASSERT(swatch1 != nil);
TPatternSwatch* swatch2 = dynamic_cast<TPatternSwatch*>(this->FindSubPane("Pattern"));
ASSERT(swatch2 != nil);
TRGBColor color = swatch1->GetColor();
Pattern pattern = swatch2->GetPattern();
bool handled = Inherited::HandleContextMenu(event);
// Swatch commands post a command to perform the change.
if (handled && TCommand::ExecuteCommands(true))
TMenuBar::Invalidate();
// We can't use CClickNotifier because we need to call SetData
// after the swatch handles the click.
if (handled && (swatch1->GetColor() != color) || (swatch2->GetPattern() != pattern)) {
SPen traits = this->GetData();
this->SetData(traits);
}
POSTCONDITION(true);
return handled;
}
#pragma mark ハ
//---------------------------------------------------------------
//
// CPenDialog::OnReanimated
//
//---------------------------------------------------------------
void CPenDialog::OnReanimated()
{
Inherited::OnReanimated();
CRandomWalk* walk = dynamic_cast<CRandomWalk*>(this->FindSubPane("Random Walk"));
walk->AddBehaviorToFront(new CClickNotifier(this, "Clicked Walk"));
TTextBox* textbox = dynamic_cast<TTextBox*>(this->FindSubPane("Width"));
textbox->AddListener(this);
textbox = dynamic_cast<TTextBox*>(this->FindSubPane("Height"));
textbox->AddListener(this);
textbox = dynamic_cast<TTextBox*>(this->FindSubPane("PixPat ID"));
textbox->AddListener(this);
TSubPaneIterator iter = this->begin(kRecursive);
while (iter != this->end()) {
TPane* subPane = *iter;
++iter;
if (TControl* control = dynamic_cast<TControl*>(subPane))
if (dynamic_cast<TPushButton*>(control) == nil) // we're already listening to the push buttons
control->AddListener(this);
}
}
//---------------------------------------------------------------
//
// CPenDialog::OnBroadcast (SControlMessage)
//
//---------------------------------------------------------------
void CPenDialog::OnBroadcast(const SControlMessage& mesg)
{
Inherited::OnBroadcast(mesg);
if (dynamic_cast<TPushButton* const>(mesg.control) == nil) {
SPen pen = this->GetData();
this->SetData(pen);
}
}
//---------------------------------------------------------------
//
// CPenDialog::OnBroadcast (TTextBox*)
//
//---------------------------------------------------------------
void CPenDialog::OnBroadcast(TTextBox* const& mesg)
{
if (mesg->GetTextLength() > 0) {
SPen pen = this->GetData();
this->SetData(pen);
}
}
//---------------------------------------------------------------
//
// CPenDialog::OnMenuCommand
//
//---------------------------------------------------------------
bool CPenDialog::OnMenuCommand(const MenuCommand& command)
{
bool handled = true;
if (command == "Clicked Walk") {
CRandomWalk* walk = dynamic_cast<CRandomWalk*>(this->FindSubPane("Random Walk"));
walk->Restart();
} else
handled = Inherited::OnMenuCommand(command);
return handled;
}
//---------------------------------------------------------------
//
// CPenDialog::SetData
//
//---------------------------------------------------------------
void CPenDialog::SetData(const SPen& pen)
{
TTextBox* textbox = nil;
// Width
textbox = dynamic_cast<TTextBox*>(this->FindSubPane("Width"));
textbox->SetValue(pen.size.width);
// Height
textbox = dynamic_cast<TTextBox*>(this->FindSubPane("Height"));
textbox->SetValue(pen.size.height);
// Mode
TControl* control = dynamic_cast<TControl*>(this->FindSubPane("Mode"));
control->SetValue(pen.mode - patCopy + 1);
// Color
TColorSwatch* swatch1 = dynamic_cast<TColorSwatch*>(this->FindSubPane("Color"));
swatch1->SetColor(pen.color);
// Pattern
TPatternSwatch* swatch2 = dynamic_cast<TPatternSwatch*>(this->FindSubPane("Pattern"));
swatch2->SetPattern(pen.pattern);
// PixPat ID
textbox = dynamic_cast<TTextBox*>(this->FindSubPane("PixPat ID"));
textbox->SetValue(pen.pixPatID);
// Walker
CRandomWalk* walk = dynamic_cast<CRandomWalk*>(this->FindSubPane("Random Walk"));
walk->SetPen(pen);
}
//---------------------------------------------------------------
//
// CPenDialog::GetData
//
//---------------------------------------------------------------
SPen CPenDialog::GetData() const
{
SPen pen;
TTextBox* textbox = nil;
// Width
textbox = dynamic_cast<TTextBox*>(this->FindSubPane("Width"));
pen.size.width = textbox->GetValue();
// Height
textbox = dynamic_cast<TTextBox*>(this->FindSubPane("Height"));
pen.size.height = textbox->GetValue();
// Mode
TControl* control = dynamic_cast<TControl*>(this->FindSubPane("Mode"));
pen.mode = control->GetValue() + patCopy - 1;
// Color
TColorSwatch* swatch = dynamic_cast<TColorSwatch*>(this->FindSubPane("Color"));
pen.color = swatch->GetColor();
// Pattern
TPatternSwatch* swatch2 = dynamic_cast<TPatternSwatch*>(this->FindSubPane("Pattern"));
pen.pattern = swatch2->GetPattern();
// PixPat ID
textbox = dynamic_cast<TTextBox*>(this->FindSubPane("PixPat ID"));
pen.pixPatID = textbox->GetValue();
if (pen.pixPatID != 0)
pen.pixPat = GetPixPat(pen.pixPatID); // ignore errors
return pen;
}